﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Forms;

using OpenNI;
using NUnit.Framework;
using MathNet.Numerics;
using System.IO; //streamwriters
using BTKinect.DataType;
using System.Threading;

namespace BTKinect
{
    class KinectReadData : FileHandling, IDataHandling
    {
        #region MEMBERS
        private KinectData kd = new KinectData(1800);
        private bool blReadWithSucces = false;
        #endregion

        #region IDATAHANDLING
        public List<Dictionary<SkeletonJoint, KinectPoint3D>> Data
        {
            get
            {
                return kd.Data;
            }
        }
        public Dictionary<int, Dictionary<SkeletonJoint, KinectPoint3D>> DataWithTime
        {
            get
            {
                return kd.DataAndTime;
            }
        }
        public List<int> Time
        {
            get
            {
                return kd.Time;
            }
        }
        public void Initialize()
        {
            OpenFile();
            if (FileFound)
                readTxtFile();
            else
                MessageBox.Show("Geen bestand gevonden of aangemaakt", "Melding", MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
        }
        public KinectData GetKinectData
        {
            get 
            { 
                if(kd == null)
                    throw new System.ArgumentException("Geen data aanwezig!", "original");
                else
                return kd; 
            }
        }
        #endregion

        #region METHODS
        private void readTxtFile()
        {
            string s;
            //instantiate _dataAndTime
            Dictionary<int, Dictionary<SkeletonJoint, KinectPoint3D>> dataAndTime = new Dictionary<int, Dictionary<SkeletonJoint, KinectPoint3D>>(1000);
            Point3D[] pnts = new Point3D[15];

            //lees bestand in een List bestaande uit strings
            try
            {
                StreamReader sr = new StreamReader(FileLocationAndFileName);
                List<string> lstString = new List<string>(1800);
                while ((s = sr.ReadLine()) != null)
                {
                    lstString.Add(s);
                }
                kd.DataInStringForm = lstString;

                //test if a Raw data file is imported
                string test = kd.DataInStringForm[2];
                if (!(test == StringHeaderRaw || test == StringHeaderRawMarker))
                {
                    kd.DataInStringForm.Clear();
                    throw new ArgumentException();
                }
                blReadWithSucces = true;
            }
            catch (Exception e)
            {
                blReadWithSucces = false;
                MessageBox.Show(e.Message + "\n Fout in het gekozen tekstbestand (controleer of het bestand 45 kolommen aan ruwe data bevat) (zie klasse KinectReadData)", "Verkeerd bestand!", MessageBoxButtons.OK, MessageBoxIcon.Error);
                blReadWithSucces = false;
            }

            if (blReadWithSucces)
            {
                //zet tekst om in data
                try
                {
                    StreamReader sr = new StreamReader(FileLocationAndFileName);

                    //read header
                    do
                    {
                        sr.ReadLine().StartsWith("*");
                    } while (sr.Peek() == '*');


                    while ((s = sr.ReadLine()) != null) //read to end of file
                    {
                        float[] data;

                        //put value in array
                        string[] dataText = s.Split('\t');

                        //first item is time
                        int tijd = Convert.ToInt32(dataText[0]);

                        //iterate through line
                        if (dataText[46] == " ") //no marker
                        {
                            data = new float[46];
                            int teller = -1;
                            for (int i = 1; i < dataText.Length - 1; i = i + 3) //15x
                            {
                                Point3D pnt = new Point3D();
                                if (dataText[i] != "" && dataText[i + 1] != "" && dataText[i + 2] != "")
                                {
                                    pnt.X = (float)Convert.ToDouble(dataText[i]);
                                    pnt.Y = (float)Convert.ToDouble(dataText[i + 1]);
                                    pnt.Z = (float)Convert.ToDouble(dataText[i + 2]);
                                }
                                pnts[++teller] = pnt;
                            }
                            kd.WitMarkerData = false;
                        }
                        else //has marker
                        {
                            data = new float[47];
                            int teller = -1;
                            for (int i = 2; i < dataText.Length - 1; i = i + 3) //15x ignore marker column
                            {
                                Point3D pnt = new Point3D();
                                if (dataText[i] != "" && dataText[i + 1] != "" && dataText[i + 2] != "")
                                {
                                    pnt.X = (float)Convert.ToDouble(dataText[i]);
                                    pnt.Y = (float)Convert.ToDouble(dataText[i + 1]);
                                    pnt.Z = (float)Convert.ToDouble(dataText[i + 2]);
                                }
                                pnts[++teller] = pnt;
                            }
                            kd.WitMarkerData = true;
                        }

                        //put values in dictionary
                        Dictionary<SkeletonJoint, KinectPoint3D> d = new Dictionary<SkeletonJoint, KinectPoint3D>(15);
                        KinectPoint3D sjp = new KinectPoint3D();
                        sjp = pnts[0];
                        d.Add(SkeletonJoint.Head, sjp);
                        sjp = pnts[1];
                        d.Add(SkeletonJoint.Neck, sjp);
                        sjp = pnts[2];
                        d.Add(SkeletonJoint.LeftShoulder, sjp);
                        sjp = pnts[3];
                        d.Add(SkeletonJoint.LeftElbow, sjp);
                        sjp = pnts[4];
                        d.Add(SkeletonJoint.LeftHand, sjp);
                        sjp = pnts[5];
                        d.Add(SkeletonJoint.RightShoulder, sjp);
                        sjp = pnts[6];
                        d.Add(SkeletonJoint.RightElbow, sjp);
                        sjp = pnts[7];
                        d.Add(SkeletonJoint.RightHand, sjp);
                        sjp = pnts[8];
                        d.Add(SkeletonJoint.Torso, sjp);
                        sjp = pnts[9];
                        d.Add(SkeletonJoint.LeftHip, sjp);
                        sjp = pnts[10];
                        d.Add(SkeletonJoint.LeftKnee, sjp);
                        sjp = pnts[11];
                        d.Add(SkeletonJoint.LeftFoot, sjp);
                        sjp = pnts[12];
                        d.Add(SkeletonJoint.RightHip, sjp);
                        sjp = pnts[13];
                        d.Add(SkeletonJoint.RightKnee, sjp);
                        sjp = pnts[14];
                        d.Add(SkeletonJoint.RightFoot, sjp);

                        //put data in dictionaries
                        dataAndTime.Add(tijd, d);
                    }
                    kd.DataAndTime = dataAndTime;
                    blReadWithSucces = true;
                }
                catch (Exception e)
                {
                    blReadWithSucces = false;
                    MessageBox.Show(e.Message, "Fout in het gekozen tekstbestand of de class KinectReadData", MessageBoxButtons.OK, MessageBoxIcon.Error);
                }
            }
        }

        public bool ReadWithSucces
        {
            get { return blReadWithSucces; }
        }
        #endregion
    }
}

